
class MovingEntity:
    def __init__(self, x, y):
        self.pos = Vector(x, y)
        self.dir = Vector(1, 0)
        self.vel = 5.0
        self.acc_dir = Vector(0, 0)
        self.colour = (255, 0, 0)
        self.radius = 3

    def Update(self, delta, engine):
        pos = self.pos + (self.dir * (delta / 100.0))
        x, y = int(pos.x / 16), int(pos.y / 16)
        if engine.arena_map.navGraph.width - 1 < x \
                or engine.arena_map.navGraph.height - 1 < y \
                or x < 0 or y < 0:
            self.out_of_bounds(pos, engine)  
        elif engine.arena_map.navGraph.get_node(x, y).accessible == False:
            self.collision(pos, engine)
        else:
            self.pos = pos

    def Render(self, surface):
        pygame.draw.circle(surface, self.colour, self.pos.tuple(), self.radius)

class Particle(MovingEntity):
    def __init__(self, pos):
        MovingEntity.__init__(self, pos.x, pos.y)
        self.pos = pos.clone()
        self.vel = 8.0
    def out_of_bounds(self, pos, engine):
        engine.particles.remove(self)
    def collision(self, pos, engine):
        engine.particles.remove(self)

class Rocket(MovingEntity):
    def __init__(self, pos):
        MovingEntity.__init__(self, pos.x, pos.y)
        self.pos = pos.clone()
        self.vel = 9.0
    def out_of_bounds(self, pos, engine):
        engine.particles.remove(self)
    def collision(self, pos, engine):
        engine.arena_map.navGraph.get_node(int(pos.x/16.0), int(pos.y/16.0)).accessible = True
        engine.arena_map.GenerateWalls()
        engine.arena_map.CreateRenderGroup()
        engine.particles.remove(self)

class Missile(MovingEntity):
    def __init__(self, pos, target, engine):
        MovingEntity.__init__(self, pos.x, pos.y)
        path_planner = PathPlanner(self, engine.arena_map.navGraph)
        path = path_planner.CreatePathToPosition(target)
        self.target = path.pop()
        self.path = path
        target_pos = self.target.pos.clone()
        target_pos.x = target_pos.x * 16 + 8
        target_pos.y = target_pos.y * 16 + 8
        self.dir =    target_pos - self.pos
        self.dir.normalise(5)
    def Update(self, delta, engine):
        #MovingEntity.Update(self,delta, engine)
        #modified_pos = tuple([int(x / 16) for x in self.target.pos])
        self.pos = self.pos  + (self.dir * (delta / 100.0))
        #self.pos = self.target.pos.clone()
        #self.pos.x = self.pos.x * 16
        #self.pos.y = self.pos.y * 16
        target_pos = self.target.pos.clone()
        target_pos.x = target_pos.x * 16 + 8
        target_pos.y = target_pos.y * 16 + 8
        self.dir =    target_pos - self.pos
        self.dir.normalise(5)
        modified_pos = int(self.pos.x / 16), int(self.pos.y / 16)
        if self.target.pos.x == modified_pos[0] and self.target.pos.y == modified_pos[1] \
                and len(self.path) > 0:
            self.target = self.path.pop()
            target_pos = self.target.pos.clone()
            target_pos.x = target_pos.x *16 + 8
            target_pos.y = target_pos.y *16 + 8
            self.dir =  target_pos - self.pos
            self.dir.normalise(5)
        if len(self.path) == 0:
            engine.particles.remove(self)
    def out_of_bounds(self, pos, engine):
        engine.particles.remove(self)
    def collision(self, pos, engine):
        engine.particles.remove(self)

class Pistol:
    def __init__(self):
        self.name = "Pistol"
        self.ammo = -1
    def fire(self, character, event, engine):
        dir = Vector(*event.pos) - character.pos
        particle = Particle(character.pos)
        dir.normalise(particle.vel)
        particle.dir = dir
        return particle
        
class RocketLauncher:
    def __init__(self):
        self.name = "Rockets"
        self.ammo = 10
    def fire(self, character, event, engine):
        if self.ammo == 0:
            return None
        dir = Vector(*event.pos) - character.pos
        rocket = Rocket(character.pos)
        dir.normalise(rocket.vel)
        rocket.dir = dir
        self.ammo -= 1
        return rocket

class MissileLauncher:
    def __init__(self):
        self.name = "Seeker"
        self.ammo = -1
    def fire(self, character, event, engine):
        if self.ammo == 0:
            return None
        missile = Missile(character.pos, event.pos, engine)
        return missile

class ControlableEntity(MovingEntity):
    def __init__(self, x, y):
        #super(ControlableEntity, self).__init__(x, y)
        MovingEntity.__init__(self, x, y)
        self.dir = Vector(0, 0)
        self.weapon = Pistol()
        self.weapon_index = 0
        self.weapons = [
            self.weapon,
            RocketLauncher(),
            MissileLauncher(),
        ]
        self.colour = (0, 0, 0)
        self.radius = 5
    def toggle_weapon(self):
        self.weapon_index += 1
        self.weapon_index %= len(self.weapons)
        self.weapon = self.weapons[self.weapon_index]
    def out_of_bounds(self, pos, engine):
        pass
    def collision(self, pos, engine):
        pass

    def move_right(self, event):
        if event.type == KEYDOWN:
            self.dir.x += 3
        elif event.type == KEYUP:
            self.dir.x -= 3

    def move_left(self, event):
        if event.type == KEYDOWN:
            self.dir.x -= 3
        elif event.type == KEYUP:
            self.dir.x += 3

    def move_up(self, event):
        if event.type == KEYDOWN:
            self.dir.y -= 3
        elif event.type == KEYUP:
            self.dir.y += 3

    def move_down(self, event):
        if event.type == KEYDOWN:
            self.dir.y += 3
        elif event.type == KEYUP:  
            self.dir.y -= 3
    def Fire(self, event, engine):
        return self.weapon.fire(self, event, engine)
        
class Enemy(MovingEntity):
    def __init__(self, x, y):
        MovingEntity.__init__(self, x, y)
        self.dir = Vector(0, 0)
        # Implement state transitions

class Trigger:
    """ Used by the mapnode to hold extra items """
    pass

class Troll(MovingEntity):
    def __init__(self, pos, engine):
        MovingEntity.__init__(self, pos.x, pos.y)
        self.colour = (21, 125, 0)
        path_planner = PathPlanner(self, engine.arena_map.navGraph)
        path = path_planner.CreatePathToPosition(engine.g.pos.tuple())
        path.pop()
        self.target = path.pop()
        self.path = path
        target_pos = self.target.pos.clone()
        target_pos.x = target_pos.x * 16 + 8
        target_pos.y = target_pos.y * 16 + 8
        self.dir =    target_pos - self.pos
        self.dir.normalise(5)
        self.radius = 8
    def Update(self, delta, engine):
        MovingEntity.Update(self,delta, engine)
        #modified_pos = tuple([int(x / 16) for x in self.target.pos])
        #self.pos = self.pos  + (self.dir * (delta / 100.0))
        #self.pos = self.target.pos.clone()
        #self.pos.x = self.pos.x * 16
        #self.pos.y = self.pos.y * 16
        target_pos = self.target.pos.clone()
        target_pos.x = target_pos.x * 16 + 8
        target_pos.y = target_pos.y * 16 + 8
        self.dir =    target_pos - self.pos
        self.dir.normalise(5)
        modified_pos = int(self.pos.x / 16), int(self.pos.y / 16)
        if self.target.pos.x == modified_pos[0] and self.target.pos.y == modified_pos[1]:
            if len(self.path) == 0:
                #path_planner = PathPlanner(self, engine.arena_map.navGraph)
                #path = path_planner.CreatePathToPosition(engine.g.pos.tuple())
                #self.target = path.pop()
                #self.path = path
                class Foo: pass
                self.target = Foo()
                self.target.pos = engine.g.pos.clone()
                #self.target = 
                self.target.pos.x = int(self.target.pos.x / 16.0)
                self.target.pos.y = int(self.target.pos.y / 16.0)
                #self.dir = target_pos - self.pos
                #self.dir.normalise(5)
                return
                
            self.target = self.path.pop()
            target_pos = self.target.pos.clone()
            target_pos.x = target_pos.x *16 + 8
            target_pos.y = target_pos.y *16 + 8
            self.dir =  target_pos - self.pos
            self.dir.normalise(5)
    def out_of_bounds(self, pos, engine):
        engine.enemies.remove(self)
    def collision(self, pos, engine):
        pass
        #engine.enemies.remove(self)
        
